import React, { useRef, useState, useCallback, useEffect, Suspense } from 'react';
import { useDrop } from 'react-dnd';
import type { WidgetMaterial, ResizeType, actionState, RulerContentState } from '../types/prevViewTypes';
import { throttle } from '../utils/common';
import ShapePoint from './ShapePoint';
import { useSelector } from 'react-redux';

import BigNumber from 'bignumber.js';
import * as echarts from 'echarts';

import { v4 as uuidv4 } from 'uuid';

import ComponentMap from './widgets/componentMap';
import ErrorBoundary from './ErrorBoundary';

// 定义数据项类型接口
interface EchartDataItem {
  xTime: string;
  yValue: string; // 原始数据为字符串类型的数值
}

/**
 * 生成ECharts配置项的钩子
 * @returns 接收数据并返回ECharts配置的函数
 */
const useOption = () => {
  // 明确返回函数的参数和返回值类型
  return (data: EchartDataItem[]): echarts.EChartsOption => ({
    color: ['#666666'],
    title: {
      text: '图表y轴时间',
      textAlign: 'left',
      textStyle: {
        color: '#666666',
        fontSize: 12,
        fontWeight: 'lighter',
        fontFamily: 'Lato',
      },
    },
    grid: {
      left: '2%',
      right: '3%',
      top: '15%',
      bottom: '2%',
      containLabel: true,
    },
    xAxis: [
      {
        axisLine: {
          lineStyle: {
            color: '#666666',
            width: 1,
          },
        },
        data: data.map((item) => item.xTime),
        axisLabel: {
          formatter: (value: string) => value,
        },
        boundaryGap: false,
      },
    ],
    yAxis: [
      {
        position: 'left',
        type: 'value',
        scale: true,
        axisLine: {
          lineStyle: {
            color: '#666666',
            width: 1,
          },
        },
        splitLine: {
          lineStyle: {
            color: '#666666',
            width: 0.5,
            opacity: 0.2,
          },
        },
        axisLabel: {
          formatter: (value: number) => new BigNumber(value).toString(),
        },
        boundaryGap: ['5%', '2%'],
      },
      {
        position: 'right',
        type: 'value',
        axisLine: {
          lineStyle: {
            color: '#666666',
            width: 1,
          },
        },
      },
    ],
    series: [
      {
        name: '测试图表',
        type: 'line',
        yAxisIndex: 0,
        lineStyle: {
          color: '#666666',
          width: 1,
        },
        symbol: 'none',
        data: data.map((item) => new BigNumber(item.yValue).toNumber()),
      },
    ],
  });
};

// 明确图表数据类型
const echartData: EchartDataItem[] = [
  { xTime: '2020-01-01', yValue: '1500' },
  { xTime: '2020-01-02', yValue: '5220' },
  { xTime: '2020-01-03', yValue: '4000' },
  { xTime: '2020-01-04', yValue: '3500' },
  { xTime: '2020-01-05', yValue: '7800' },
];

const Gridarea: React.FC = () => {
  const innerDivRef = useRef<HTMLDivElement>(null);
  const parseOption = useOption();
  const scale = useSelector((state: RulerContentState) => state.ruler.scales);
  const [transform, setTransform] = useState({ transform: `scale(1)` });

  const [droppedItems, setDroppedItems] = useState<WidgetMaterial[]>([]);
  const [gridChecked, setGridChecked] = useState<number>(0);
  const [gridMouseId, setGridMouseId] = useState<number>(0);

  // 统一管理操作状态，避免拖拽和拉伸冲突
  const [actionState, setActionState] = useState<{
    type: 'none' | 'dragging' | 'resizing';
    data: ResizeType | actionState | any; // 存储当前操作的上下文数据
  }>({ type: 'none', data: null });

  const [{ isOver }, drop] = useDrop<WidgetMaterial, { name: string }, { isOver: boolean }>(() => ({
    accept: ['chart', 'table', 'button', 'input'],
    drop: (item, monitor) => {
      setGridChecked(item.id);
      setGridMouseId(item.id);

      // const sourceClientOffset = monitor.getSourceClientOffset(); // 源元素坐标
      const clientOffset = monitor.getClientOffset(); // 当前鼠标坐标
      const containerRect = innerDivRef.current?.getBoundingClientRect(); // 目标容器坐标

      if (clientOffset && containerRect) {
        // 修复初始放置位置计算，使用元素自身宽高的一半作为偏移
        item.pt.left = clientOffset.x - containerRect.left - item.initialW / 2;
        item.pt.top = clientOffset.y - containerRect.top - item.initialH / 2;
        item.uuid = uuidv4();
        // 当项目被放置时，将其添加到状态中
        setDroppedItems((prev: WidgetMaterial[]) => [...prev, item]);
      }
      return { name: 'GridArea' };
    },
    collect: (monitor) => ({
      isOver: !!monitor.isOver(),
    }),
  }));
  drop(innerDivRef);

  const handleGridItemCheck = () => {
    setGridChecked(0);
  };

  // 全局鼠标事件处理（合并拖拽和拉伸的移动逻辑）
  const handleGlobalMouseMove = useCallback(
    throttle((e: MouseEvent) => {
      const { type, data } = actionState;
      if (type === 'none') return;

      const containerRect = innerDivRef.current?.getBoundingClientRect();
      if (!containerRect) return;

      // 拖拽处理
      if (type === 'dragging') {
        const { item, offset } = data;
        const newLeft = e.clientX - containerRect.left - offset.x;
        const newTop = e.clientY - containerRect.top - offset.y;

        setDroppedItems((prev) =>
          prev.map((i) => (i.id === item.id ? { ...i, pt: { ...i.pt, left: newLeft, top: newTop } } : i))
        );
      }

      // 拉伸处理
      if (type === 'resizing') {
        const { itemId, position, startX, startY, startWidth, startHeight, startLeft, startTop, fixedPoint } = data;
        const deltaX = e.clientX - startX;
        const deltaY = e.clientY - startY;

        let newWidth = startWidth;
        let newHeight = startHeight;
        let newLeft = startLeft;
        let newTop = startTop;

        // 根据不同控制点计算新尺寸和位置，确保对角固定
        switch (position) {
          case 't': {
            // 上边拖动，下边固定
            newTop = startTop + deltaY;
            newHeight = startHeight - deltaY;
            break;
          }
          case 'r': {
            // 右边拖动，左边固定
            newWidth = startWidth + deltaX;
            break;
          }
          case 'b': {
            // 下边拖动，上边固定
            newHeight = startHeight + deltaY;
            break;
          }
          case 'l': {
            // 左边拖动，右边固定
            newLeft = startLeft + deltaX;
            newWidth = startWidth - deltaX;
            break;
          }
          case 'lt': {
            // 左上角拖动，右下角固定
            newLeft = startLeft + deltaX;
            newTop = startTop + deltaY;
            newWidth = fixedPoint.x - newLeft;
            newHeight = fixedPoint.y - newTop;
            break;
          }
          case 'rt': {
            // 右上角拖动，左下角固定
            newTop = startTop + deltaY;
            newWidth = startWidth + deltaX;
            newHeight = fixedPoint.y - newTop;
            break;
          }
          case 'lb': {
            // 左下角拖动，右上角固定
            newLeft = startLeft + deltaX;
            newWidth = fixedPoint.x - newLeft;
            newHeight = startHeight + deltaY;
            break;
          }
          case 'rb': {
            // 右下角拖动，左上角固定
            newWidth = startWidth + deltaX;
            newHeight = startHeight + deltaY;
            break;
          }
        }

        // 应用最小尺寸限制
        newWidth = Math.max(100, newWidth);
        newHeight = Math.max(100, newHeight);

        // 更新元素
        setDroppedItems((prev) =>
          prev.map((i) =>
            i.id === itemId
              ? {
                  ...i,
                  initialW: newWidth,
                  initialH: newHeight,
                  pt: { left: newLeft, top: newTop },
                  t: { top: 0, left: i.initialW / 2 },
                  r: { top: i.initialH / 2, left: i.initialW - 3 },
                  b: { top: i.initialH - 3, left: i.initialW / 2 },
                  l: { top: i.initialH / 2, left: 0 },
                  lt: { top: 0, left: 0 },
                  rt: { top: 0, left: i.initialW - 3 },
                  rb: { top: i.initialH - 3, left: i.initialW - 3 },
                  lb: { top: i.initialH - 3, left: 0 },
                }
              : i
          )
        );
      }
    }, 16),
    [actionState]
  );

  // 全局鼠标抬起处理（统一结束操作）
  const handleGlobalMouseUp = useCallback(() => {
    setActionState({ type: 'none', data: null });
  }, []);

  // 自动管理全局事件监听
  useEffect(() => {
    if (actionState.type !== 'none') {
      document.addEventListener('mousemove', handleGlobalMouseMove);
      document.addEventListener('mouseup', handleGlobalMouseUp);
    }
    return () => {
      document.removeEventListener('mousemove', handleGlobalMouseMove);
      document.removeEventListener('mouseup', handleGlobalMouseUp);
    };
  }, [actionState.type, handleGlobalMouseMove, handleGlobalMouseUp]);

  useEffect(() => {
    // 仅在 scale 变化时更新 transform 并打印
    setTransform({ transform: `scale(${scale})` });
  }, [scale]); // 仅依赖 scale

  // onMouseDown 鼠标按下事件
  const handleGridItemDown = useCallback(
    (e: React.MouseEvent, val: WidgetMaterial) => {
      e.stopPropagation();
      e.preventDefault();
      // 如果正在拉伸，不响应拖拽
      if (actionState.type === 'resizing') return;

      setGridChecked(val.id);
      const containerRect = innerDivRef.current?.getBoundingClientRect();
      if (containerRect) {
        const elementLeft = containerRect.left + val.pt.left;
        const elementTop = containerRect.top + val.pt.top;

        // 设置拖拽状态
        setActionState({
          type: 'dragging',
          data: {
            item: val,
            offset: {
              x: e.clientX - elementLeft,
              y: e.clientY - elementTop,
            },
          },
        });
      }
    },
    [actionState.type]
  );

  const handleGridItemEnter = useCallback(
    (e: React.MouseEvent, val: WidgetMaterial) => {
      e.stopPropagation();
      if (gridMouseId !== val.id) setGridMouseId(val.id);
    },
    [gridMouseId]
  );

  const handleGridItemLeave = useCallback((e: React.MouseEvent) => {
    e.stopPropagation();
    setGridMouseId(0);
  }, []);

  const checkedClassName = (val: WidgetMaterial) => {
    const base = 'shape-modal-change';
    if (gridChecked === val.id) return `${base} selectActive`;
    if (gridMouseId === val.id && gridChecked != gridMouseId) return `${base} hoverActive`;
    return base;
  };

  // 控制点点击处理
  const handlePointClick = useCallback(
    (pos: keyof WidgetMaterial, e: React.MouseEvent) => {
      e.stopPropagation();
      e.preventDefault();

      // 只处理对角控制点
      if (!['t', 'r', 'b', 'l', 'lt', 'rt', 'lb', 'rb'].includes(pos)) return;

      // 如果正在拖拽，不响应拉伸
      if (actionState.type === 'dragging') return;

      const item = droppedItems.find((i) => i.id === gridChecked);
      if (!item) return;

      // 计算固定点坐标（对角点）- 关键优化
      let fixedPoint = { x: 0, y: 0 };
      switch (pos) {
        case 'lt':
          // 左上角拖动，右下角固定
          fixedPoint = {
            x: item.pt.left + item.initialW,
            y: item.pt.top + item.initialH,
          };
          break;
        case 'rt':
          // 右上角拖动，左下角固定
          fixedPoint = {
            x: item.pt.left,
            y: item.pt.top + item.initialH,
          };
          break;
        case 'lb':
          // 左下角拖动，右上角固定
          fixedPoint = {
            x: item.pt.left + item.initialW,
            y: item.pt.top,
          };
          break;
        case 'rb':
          // 右下角拖动，左上角固定
          fixedPoint = {
            x: item.pt.left,
            y: item.pt.top,
          };
          break;
      }

      // 设置拉伸状态，包含固定点信息
      setActionState({
        type: 'resizing',
        data: {
          itemId: item.id,
          position: pos,
          startX: e.clientX,
          startY: e.clientY,
          startLeft: item.pt.left,
          startTop: item.pt.top,
          startWidth: item.initialW,
          startHeight: item.initialH,
          fixedPoint: fixedPoint, // 存储固定点坐标
        },
      });
    },
    [actionState.type, gridChecked, droppedItems]
  );

  // 控制点位置列表（避免重复书写）
  const pointPositions: (keyof WidgetMaterial)[] = ['t', 'r', 'b', 'l', 'lt', 'rt', 'lb', 'rb'];

  // 动态组件加载器：根据类型返回对应组件
  const renderWidget = (item: WidgetMaterial) => {
    const WidgetComponent = ComponentMap[item.type as keyof typeof ComponentMap]; // 从映射表获取组件
    if (!WidgetComponent) {
      return <div>未知组件类型: {item.type}</div>;
    }

    // 使用React.memo缓存组件，避免无意义重渲染
    const MemoizedWidget = React.memo(WidgetComponent);

    return (
      <ErrorBoundary fallback={<div>组件 {item.type} 加载失败</div>}>
        <Suspense fallback={<div>加载中...</div>}>
          <MemoizedWidget
            // 传递组件所需的props（根据实际需求调整）
            option={item.type === 'chart' ? parseOption(echartData) : undefined}
            style={{ height: item.initialH, width: item.initialW, backgroundColor: 'transparent' }}
            // 其他通用props
          />
        </Suspense>
      </ErrorBoundary>
    );
  };

  return (
    <div
      ref={innerDivRef}
      style={{
        width: 1920,
        height: 1080,
        marginLeft: `${(3840 - 1920 - 60) / 2}px`,
        marginTop: `${(2160 - 1080 - 10) / 2}px`,
        backgroundColor: isOver ? 'rgba(0, 255, 0, 0.1)' : '#f2f3f5',
        position: 'relative',
        boxShadow: '0 8px 10px #00000012',
        transition: 'all .4s',
        overflow: 'hidden',
        ...transform,
      }}
      onClick={handleGridItemCheck}
    >
      {droppedItems.map((item) => (
        <div
          className="grid-item"
          style={{
            zIndex: 1 + gridChecked,
            ...item.pt,
            position: 'absolute',
            width: item.initialW,
            height: item.initialH,
          }}
          key={item.uuid}
          onClick={(e) => e.stopPropagation()}
          onMouseDown={(e) => handleGridItemDown(e, item)}
          // onMouseMove={(e) => handleGridItemMove(e, item)}
          // onMouseUp={(e) => handleGridItemUp(e)}
          onMouseEnter={(e) => handleGridItemEnter(e, item)}
          onMouseLeave={(e) => handleGridItemLeave(e)}
        >
          {/* 循环渲染控制点（复用组件） */}
          {gridChecked === item.id &&
            pointPositions.map((pos) => (
              <ShapePoint key={pos} position={pos} item={item} onPointClick={handlePointClick} />
            ))}
          <div className="shape-modal" style={{ width: item.initialW, height: item.initialH }}>
            <div className={'shape-modal-select ' + (gridChecked === item.id ? 'active' : '')}></div>
            <div className={checkedClassName(item)}></div>
          </div>
          {/*  */}
          {/* <CommonChart
                option={parseOption(echartData)} // 修正多余参数问题
                notMerge
                lazyUpdate
                style={{ height: item.initialH, width: item.initialW, backgroundColor: 'transparent' }}
              /> */}
          {/* 动态渲染组件 */}
          {renderWidget(item)}
        </div>
      ))}
    </div>
  );
};

export default Gridarea;
